package lib.bone.admin.controller.research;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lib.bone.access.module.dict.impl.PaperDictServiceImpl;
import lib.bone.admin.anno.FormLock;
import lib.bone.access.constant.ResearchTypeConst;
import lib.bone.audit.workload.domain.NepuWorkload;
import lib.bone.flow.domain.dto.PaperFlowWorkDTO;
import lib.bone.nepudata.dao.NepuPaperDAO;
import lib.bone.nepudata.domain.dto.paper.NepuPaperAddDTO;
import lib.bone.nepudata.domain.dto.paper.NepuPaperQueryDTO;
import lib.bone.nepudata.domain.dto.paper.NepuPaperUpdateDTO;
import lib.bone.nepudata.domain.entity.NepuPaper;
import lib.bone.access.module.dict.entity.NepuPaperDict;
import lib.bone.ext.draft.NepuDraft;
import lib.bone.ext.draft.NepuDraftService;
import lib.bone.access.config.cycle.NepuCycle;
import lib.bone.access.config.cycle.NepuCycleService;
import lib.bone.access.module.dict.DictServiceCtl;
import lib.bone.access.module.oss.NepuResearchFileService;
import lib.bone.audit.workload.service.NepuWorkloadService;
import lib.bone.nepudata.service.NepuPaperService;
import lib.bone.nepudata.service.ResearchServiceCtl;
import lib.bone.nepudata.service.impl.NepuPaperServiceImpl;
import lib.bone.admin.anno.WebLog;
import lib.bone.admin.constant.MethodTypeConst;
import lib.bone.admin.domain.dto.FileUpdateDTO;
import lib.bone.common.constant.ResponseCodeConst;
import lib.bone.common.core.domain.ResponseDTO;
import lib.bone.common.core.redis.RedisCache;
import lib.bone.common.utils.JsonUtil;
import lib.bone.flow.constant.FlowWorkStatusConst;
import lib.bone.flow.domain.dto.FlowParam;
import lib.bone.flow.domain.entity.FlowWork;
import lib.bone.flow.service.FlowWorkCtl;
import lib.bone.flow.service.FlowWorkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.swing.text.html.Option;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * leiyusheng
 * 2022-1-12
 */

/**
 * @author: kindear
 * @date : 2022-1-13
 */
@Slf4j
@RestController
@RequestMapping("nepu")
@Api(tags = "论文")
public class NepuPaperController {

    @Autowired
    NepuDraftService draftService;

    @Autowired
    ResearchServiceCtl researchServiceCtl;


    @Autowired
    DictServiceCtl dictServiceCtl;

    @Autowired
    RedisCache redisCache;

    @Autowired
    NepuPaperServiceImpl nepuPaperService;

    @Autowired
    PaperDictServiceImpl paperDictService;

    @Autowired
    NepuResearchFileService nepuResearchFileService;

    @Autowired
    FlowWorkCtl flowWorkCtl;

    @Autowired
    NepuWorkloadService nepuWorkloadService;

    @Autowired
    NepuCycleService cycleService;

    @Autowired
    FlowWorkService flowWorkService;

    @Autowired
    NepuPaperService paperService;




    /**
     * 表单校验
     * @param dto
     * @return
     */
    public String formValid(NepuPaperAddDTO dto){
        // 表单重复性校验
        String errMsg = "";
        Long operator = StpUtil.getLoginIdAsLong();
        Long applyId = dto.getSecondAuthorId();
        if (!dto.getFirstAuthorId().equals(0L))
            applyId = dto.getFirstAuthorId();
        if (!applyId.equals(operator)){
            errMsg = "您不是负责人，无法申报该项目";
            return errMsg;
        }

        return errMsg;
    }


    @PostMapping("papers/clean")
    @ApiOperation(value = "清除标记论文",notes = "")
    public ResponseDTO cleanPapers(){
        NepuPaper t = new NepuPaper();
        // 标记为 1 的数据
        t.setStatus(1);

        // 构建 Example
        Example<NepuPaper> example = Example.of(t);

        List<NepuPaper> list = paperService.findByExample(example);

        log.info("{}篇论文被标记删除",list.size());

        return ResponseDTO.succData(list);
    }
    @WebLog(module = "nepu-access")
    @PostMapping("papers")
    @FormLock(lockKey = "PAPER_FORM")
    @ApiOperation(value = "新建记录",notes = "")
    public ResponseDTO<Object> saveOne(@RequestBody @Validated NepuPaperAddDTO nepuPaperAddDTO){
        // 1. 获取当前登录用户ID -- 自动拦截未登录用户 & 判断是否满足提交条件
        String operator = StpUtil.getLoginIdAsString();
        String firstAuthorId = nepuPaperAddDTO.getFirstAuthorId().toString();
        String secondAuthorId = nepuPaperAddDTO.getSecondAuthorId().toString();
        // 2. 表单校验
        String errMsg = formValid(nepuPaperAddDTO);
        if (!Validator.isEmpty(errMsg)){
            return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM,errMsg);
        }

        // bug fix
        if (firstAuthorId.equals("0") && !secondAuthorId.equals("0") && !operator.equals(secondAuthorId)){
            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"您不是二作，无申报权限");
        }
        if (firstAuthorId.equals(secondAuthorId) && !firstAuthorId.equals("0")){
            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"一二作不可为同一人");
        }
        List<String> dictIds = paperDictService.getDictIdsByType("成果");
        // 获取当前周期ID
//        String cycleId = cycleService.getNowResearchCycleId();
        String authorId = secondAuthorId;
        if (Validator.isNotEmpty(firstAuthorId) && !firstAuthorId.equals("0")){
            authorId = firstAuthorId;
        }
        List<NepuWorkload> workloads = nepuWorkloadService.getByUserIdAndResearchTypeAndCycleId(Long.parseLong(authorId),ResearchTypeConst.PAPER,cycleService.getNowResearchCycleId());
        // 2023-05-17
        // 获取 dict

         NepuCycle nepuCycle = cycleService.getNowResearchCycle();
        List<FlowWork> flowWorkList = flowWorkService.getPaperNumber("paper-check-01",operator);
        List<FlowWork> list = new ArrayList<>();

        //通过的或者进行中的才会占用一次机会
        Optional<NepuPaperDict> nepuPaperDict = paperDictService.getById(nepuPaperAddDTO.getPaperDictId());
        if (nepuPaperDict.isPresent()){
            if (nepuPaperDict.get().getPaperType().contains("成果转化")){

            }else {
                for (FlowWork flowWork:flowWorkList){
                    if(flowWork.getFlowWorkStatus().equals(FlowWorkStatusConst.IN_PROGRESS) || flowWork.getFlowWorkStatus().equals(FlowWorkStatusConst.FINISHED)){
                        Optional<NepuPaper> nepuPaperOp = nepuPaperService.getById(flowWork.getServiceId());
                        if (nepuPaperOp.isPresent()){
                            if (nepuPaperOp.get().getCycleId().equals(nepuCycle.getId())){
                                Optional<NepuPaperDict> nepuPaperDictOp = paperDictService.getById(nepuPaperOp.get().getPaperDictId());
                                if (nepuPaperDictOp.isPresent()){
                                    if (nepuPaperDictOp.get().getPaperType().contains("成果转化")){
                                        System.out.println("包含成果转化");
                                    }else {
                                        list.add(flowWork);
                                    }
                                }
                            }
                        }
                    }
                }
                if (list.size()>=3){
                    return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"本考核期内计算工作量的论文已达三篇的上限");
                }
            }
        }


        Integer total = 0;
        for(NepuWorkload ele:workloads){
            JSONObject jsonObject = JSONObject.parseObject(ele.getWorkloadAttach());
            String dictId = jsonObject.getString("dictId");
            // 不是成果就统计
            if (!dictIds.contains(dictId)){
                total++;
            }
        }

        // 论文第一作者工作本周期大于等于3 且 本次提交不是成果转化的进行拦截
        if (total >= 3 && !dictIds.contains(nepuPaperAddDTO.getPaperDictId())){
            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"本考核周期内第一作者的论文已有三篇获得工作量！");
        }
//        // 校验的是第二作者
//        if (!secondAuthorId.equals("0")){
//            //Integer totalNumber = nepuWorkloadService.countByUserIdAndResearchTypeAndCycleId(nepuPaperAddDTO.getSecondAuthorId(),ResearchTypeConst.PAPER,cycleService.getNowCycleId());
//            List<NepuWorkload> workloads = nepuWorkloadService.getByUserIdAndResearchTypeAndCycleId(nepuPaperAddDTO.getSecondAuthorId(),ResearchTypeConst.PAPER,cycleService.getNowResearchCycleId());
//            // 2023-05-17
//            // 获取 dict
//
//            Integer total = 0;
//            for(NepuWorkload ele:workloads){
//                JSONObject jsonObject = JSONObject.parseObject(ele.getWorkloadAttach());
//                String dictId = jsonObject.getString("dictId");
//                // 不是成果就统计
//                if (!dictIds.contains(dictId)){
//                    total++;
//                }
//            }
//
//            // 论文第一作者工作本周期大于等于3 且 本次提交不是成果转化的进行拦截
//            if (total >= 3 && !dictIds.contains(nepuPaperAddDTO.getPaperDictId())){
//                return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"本考核周期内第二作者的论文已有三篇获得工作量！");
//            }
//        }
//        Optional<NepuCycle> nepuCycleOp = cycleService.findNowCycle("科研周期");
//        if (!nepuCycleOp.isPresent()){
//            return ResponseDTO.succData(ResponseCodeConst.NOT_FOUND);
//        }
//        NepuCycle nepuCycle = new NepuCycle();
       // NepuCycle nepuCycle = cycleService.getNowResearchCycle();
       // BeanUtil.copyProperties(nepuCycleOp.get(),nepuCycle,CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
//        List<FlowWork> flowWorkList = flowWorkService.getPaperNumber("paper-check-01",operator);
//        List<FlowWork> list = new ArrayList<>();
        //通过的或者进行中的才会占用一次机会
//        for (FlowWork flowWork:flowWorkList){
//            if(flowWork.getFlowWorkStatus().equals(FlowWorkStatusConst.IN_PROGRESS) || flowWork.getFlowWorkStatus().equals(FlowWorkStatusConst.FINISHED)){
//                list.add(flowWork);
//            }
//        }
//        if (list.size()>=3){
//            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"本考核期内计算工作量的论文已达三篇的上限");
//            //return ResponseDTO.succData(ResponseCodeConst.FORBIDDEN,"本考核期内计算工作量的论文已达三篇的上限！");
//        }


        //通过的或者进行中的才会占用一次机会
//        for (FlowWork flowWork:flowWorkList){
//            if(flowWork.getFlowWorkStatus().equals(FlowWorkStatusConst.IN_PROGRESS) || flowWork.getFlowWorkStatus().equals(FlowWorkStatusConst.FINISHED)){
//                Optional<NepuPaper> paperOp = nepuPaperDAO.findById(flowWork.getServiceId());
//                if (paperOp.isPresent()){
//                    NepuPaper nepuPaper = paperOp.get();
//                    // 不是成果的才会记入
//                    if (nepuPaper.getCycleId().equals(id) && !dictIds.contains(nepuPaper.getPaperDictId())){
//                        list.add(flowWork);
//                    }
//                }
////                if (nepuPaper.get().getCycleId().equals(id)){
////                    list.add(flowWork);
////                }
//            }
//        }
//        // 现在提交的是论文
//        if (!dictIds.contains(nepuPaperAddDTO.getPaperDictId()) && list.size()>=3) {
//            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"本考核期内计算工作量的论文已达三篇的上限");
//
//        }


        // 2. 获取当前时间所在周期 -- 拦截不在周期内的提交
        NepuCycle cycle = cycleService.getNowResearchCycle();
        // 3. 获取词典信息
        Optional<Object> paperDictOp = dictServiceCtl.getById(nepuPaperAddDTO.getPaperDictId(),ResearchTypeConst.PAPER);
        if (!paperDictOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        NepuPaperDict dict = (NepuPaperDict) paperDictOp.get();
        // 4. 写入记录 并赋值最大工作量
        NepuPaper saveEntity = new NepuPaper();
        BeanUtil.copyProperties(nepuPaperAddDTO,saveEntity,CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
        saveEntity.setWorkload(dict.getWorkloadMax());
        saveEntity.setCycleId(cycleService.getNowResearchCycleId());
        //判断论文的发布时间是否在周期内cg
        if (saveEntity.getPaperPublicationTime().before(cycle.getStartDate())||
                saveEntity.getPaperPublicationTime().after(cycle.getEndDate())) {
            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"论文发表时间必须在考核周期内！");

        }else {

//            //重复性校验 -- 根据论文题目与第一作者cg
//            Optional<NepuPaper> paperOp = nepuPaperService.getByPaperTitleAndFirstAuthor(nepuPaperAddDTO.getPaperTitle(),nepuPaperAddDTO.getFirstAuthor());
//            if (paperOp.isPresent()){
//                return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM,"重复的论文题目与第一作者！");
//            }
//            saveEntity.setCycleId(cycleService.getNowCycleId());
            saveEntity.setCycleId(cycleService.getNowResearchCycleId());
            NepuPaper paper = (NepuPaper) researchServiceCtl.saveOne(saveEntity);
            // 5. 写入绑定文件信息 -- 修改为异步任务
            List<String> fileIds = nepuPaperAddDTO.getFileIds();
            nepuResearchFileService.batchBindFile(ResearchTypeConst.PAPER, paper.getId(), fileIds);
            // 6. 构建流程参数
            FlowParam flowParam = new FlowParam(ResearchTypeConst.PAPER,paper.getId(),paper.getPaperTitle(),operator,null);
            // 7. 启动流程实例 -- 修改为异步任务
            flowWorkCtl.startProcess("paper-check-01", operator, flowParam);
            return ResponseDTO.succData(paper);
        }
    }

    @WebLog(module = "nepu-access",operate = MethodTypeConst.DELETE)
    @DeleteMapping("papers/{id}")
    @ApiOperation(value = "删除单条记录",notes = "传入ID")
    public ResponseDTO<Object> deleteOne(@PathVariable("id") String id){
        return researchServiceCtl.deleteById(id,ResearchTypeConst.PAPER);
    }

    @GetMapping("papers/{id}")
    @ApiOperation(value = "查询单条记录",notes = "传入ID")
    public ResponseDTO<Object> getOne(@PathVariable("id") String id){
        Optional<Object> entityOp = researchServiceCtl.getById(id,ResearchTypeConst.PAPER);
        return entityOp.map(ResponseDTO::succData).orElseGet(() -> ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND));
    }

    /** 更新单条记录 **/
    @WebLog(module = "nepu-access",operate = MethodTypeConst.UPDATE)
    @PutMapping("papers")
    @ApiOperation(value = "更新单条记录",notes = "")
    public ResponseDTO<Object> updateOne(@RequestBody @Validated NepuPaperUpdateDTO nepuPaperUpdateDTO){
        Optional<Object> paperOp = researchServiceCtl.getById(nepuPaperUpdateDTO.getId(),ResearchTypeConst.PAPER);
        if (!paperOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        NepuPaper paper = (NepuPaper) paperOp.get();
        BeanUtil.copyProperties(nepuPaperUpdateDTO,paper,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        return ResponseDTO.succData(researchServiceCtl.updateOne(paper,ResearchTypeConst.PAPER));
    }

    @GetMapping("papers")
    @ApiOperation(value = "查询全部",notes = "")
    public ResponseDTO<Object> getAll(NepuPaperQueryDTO nepuPaperQueryDTO){
        Sort sort;
        if(nepuPaperQueryDTO.getOrder().equalsIgnoreCase("DESC")){
            sort = Sort.by(Sort.Direction.DESC, nepuPaperQueryDTO.getSortBy());
        }else {
            sort = Sort.by(Sort.Direction.ASC, nepuPaperQueryDTO.getSortBy());
        }

        // tips : 页码对应 - 1
        Pageable pageable = PageRequest.of(nepuPaperQueryDTO.getPageNum() - 1 , nepuPaperQueryDTO.getPageSize(), sort);

        NepuPaper nepuPaper = new NepuPaper();
        BeanUtil.copyProperties(nepuPaperQueryDTO,nepuPaper, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        Example<NepuPaper> example = Example.of(nepuPaper);
        return ResponseDTO.succData(researchServiceCtl.getAll(pageable,example,ResearchTypeConst.PAPER));

    }

    @WebLog(module = "nepu-access",operate = MethodTypeConst.UPDATE)
    @PutMapping("papers/files")
    @ApiOperation(value = "更新附件信息",notes = "")
    public ResponseDTO<Object> updateFiles(@RequestBody @Validated FileUpdateDTO dto){
        Long userId = StpUtil.getLoginIdAsLong();
        Optional<Object> paperOp = researchServiceCtl.getById(dto.getMapperId(),ResearchTypeConst.PAPER);
        if (!paperOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        NepuPaper paper = (NepuPaper) paperOp.get();
        if (!userId.equals(paper.getFirstAuthorId())){
            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"非负责人无法修改");
        }
        // 清理之前的附件信息
        nepuResearchFileService.deleteEntityLink(paper.getId());
        // 写入新的附件信息
        List<String> fileIds = dto.getFileIds();
        nepuResearchFileService.batchBindFile(ResearchTypeConst.PAPER,paper.getId(),fileIds);
        // 返回操作信息
        return ResponseDTO.succMsg("更新成功");
    }

    @WebLog(module = "nepu-access",operate = MethodTypeConst.UPDATE)
    @PutMapping("papers/{id}/workload")
    @ApiOperation(value = "修改记录工作量")
    public ResponseDTO<Object> updateWorkload(@PathVariable("id") String id,@RequestParam("workload") Double workload){
        Optional<Object> entityOp = researchServiceCtl.getById(id,ResearchTypeConst.PAPER);
        if (!entityOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND,"未找到对应课题记录");
        }
        NepuPaper paper = (NepuPaper) entityOp.get();
        String dictId = paper.getPaperDictId();
        Optional<Object> dictOp = dictServiceCtl.getById(dictId,ResearchTypeConst.PAPER);
        if (!dictOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND,"未找到课题关联词典记录");
        }
        NepuPaperDict dict = (NepuPaperDict) dictOp.get();
        if (workload > dict.getWorkloadMax() || workload < dict.getWorkloadMin()){
            return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM,"工作量范围错误");
        }
        paper.setWorkload(workload);
        // 写入记录
        return ResponseDTO.succData(researchServiceCtl.updateOne(paper,ResearchTypeConst.PAPER));
    }


    @Deprecated
    @PostMapping("paper/status")
    @ApiOperation(value = "查询论文更新状态")
    public ResponseDTO findStatus(){
        Long loginId = StpUtil.getLoginIdAsLong();
        if (loginId==null){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND,"未提供token！");
        }
        return nepuPaperService.status(loginId);
    }

    @PostMapping("paperFlowWork/update")
    @ApiOperation(value = "更新论文流程实例")
    public ResponseDTO updateFlowWorkList(@RequestBody PaperFlowWorkDTO dto){
        return nepuPaperService.updateList(dto);
    }


    // 草稿相关功能
    @PostMapping("papers/storage")
    @FormLock(lockKey = "PAPER_STORE",needLogin = true)
    @ApiOperation(value = "暂存记录",notes = "")
    public ResponseDTO<Object> setStorage(@RequestBody  NepuPaperAddDTO dto){
        Long userId = StpUtil.getLoginIdAsLong();
        NepuDraft draft = new NepuDraft();
        draft.setFormId(ResearchTypeConst.PAPER);
        draft.setStatus(1);
        draft.setUserId(userId);
        draft.setFormJsonStr(JsonUtil.obj2String(dto));
        return ResponseDTO.succData(draftService.saveOne(draft));
    }

    @GetMapping("papers/storage")
    @ApiOperation(value = "获取最新暂存")
    public ResponseDTO<Object> getStorage(){
        Long userId = StpUtil.getLoginIdAsLong();
        Optional<NepuDraft> draftOp = draftService.getLastDraft(userId,ResearchTypeConst.PAPER);
        if (!draftOp.isPresent()) return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        NepuDraft draft = draftOp.get();
        return ResponseDTO.succData(JsonUtil.string2Obj(draft.getFormJsonStr(),NepuPaperAddDTO.class));
    }

    @GetMapping("papers/storage/all")
    @ApiOperation(value = "获取全部暂存")
    public ResponseDTO<Object> getAllStorage(){
        Long userId = StpUtil.getLoginIdAsLong();
        List<NepuDraft> drafts = draftService.getFormAllDrafts(userId,ResearchTypeConst.PAPER);
        return ResponseDTO.succData(drafts);
    }

}
